<?php

/**
 * 视图渲染
 *
 * 负责定义视图，并将视图元素渲染成最终执行页面
 *
 * @author Lan <lanyg.com@gmail.com>
 * @link http://www.lanyg.com/projects/lanp
 * @copyright Copyright &copy; 2011-2012 Yanguang Lan (www.lanyg.com)
 * @license LGPL (http://www.gnu.org/licenses/lgpl.html)
 * @version $Id$
 */

/**
 * MVC_View
 *
 * @author Lan
 */

class MVC_View
{
    /**
     * 定义视图文件
     *
     * @access public
     * @var string $file 视图文件别名
     */

    public $file = '';

    /**
     * 定义视图变量存储单元
     *
     * @access public
     * @var array $vars 视图变量存储数组
     */

    public $vars = array();

    /**
     * 定义块元素存储单元
     *
     * @access public
     * @var array $blocks 块元素存储数组
     */

    public $blocks = array();
	
    /**
     * 定义当前块元素
     *
     * @access public
     * @var string $current_block
     */
	 
    public $current_block = null;

    /**
     * 布局清除标识符
     *
     * @access
     * @var boolean $clearLayout
     */

    public $clearLayout = false;

    /**
     * 视图输出内容
     *
     * @access public
     * @var string $contents
     */

    public $contents = '';

    /**
     * 视图缓存内容
     *
     * @access public
     * @var string $cacheContents
     */

    public $cacheContents;

    /**
     * 动态内容解析成缓存输出
     *
     * @access public
     * @var boolean $dynamicCache
     */

    public $dynamicCache;

    /**
     * 是否缓存视图
     *
     * @access public
     * @var boolean $isCache
     */

    public $isCache;
    /**
     * 缓存id
     *
     * @access public
     * @var string $cacheID
     */

    public $cacheID = null;

    /**
     * 缓存期限
     *
     * @access public
     * @var integer $expire
     */

    public $expire = 900;

    /**
     * 已缓存标志
     *
     * @access public
     * @var boolean $cached
     */

    public $cached;

    /**
     * 构造函数
     *
     * @access public
     */

    public function  __construct()
    {
        $controller_name = MVC::instance()->controllerName;
        $action_name = MVC::instance()->actionName;
        $this->isCache = MVC::instance()->config['view_cache'];
        if ( !$this->file )
            $this->file = $controller_name . DS . $action_name;

        $this->cacheID = $this->cacheID == null ? APPDIR . 'runtime' . DS . 'cache' . DS . md5($this->file).'.php' : $this->cacheID;
    }

    /**
     * 布局载入
     *
     * @access public
     * @param string $layout
     */

    public function layout($layout = 'index')
    {
	extract($this->vars);
        if ( !$this->clearLayout )
        include APPDIR . 'views' . DS . 'layout' . DS . $layout . '.php';
    }

    /**
     * 元素载入
     *
     * @access public
     * @param string $element
     */

    public function element($element = 'index')
    {	
	extract($this->vars);
        include APPDIR . 'views' . DS . 'element' . DS . $element . '.php';
    }

    /**
     * 设置视图文件
     *
     * @access public
     * @param string $file
     */

    public function setFile($file)
    {
        if ( isset($file) )
        $this->file = $file;
    }

    /**
     * 设置缓冲
     *
     * @access public
     * @param boolean $is_cache
     */

    public function setCache($is_cache)
    {
        $this->isCache = $is_cache;
    }

    /**
     * 设置过期时间(秒)
     *
     * @access public
     * @param integer $expire
     */

    public function setExpire($expire)
    {
        $this->expire = $expire;
    }

    /**
     * 设置视图变量
     *
     * @access public
     * @param string $name
     * @param mix $value
     */

    public function setVar($name, $value)
    {
        $this->vars[$name] = $value;
    }   

    /**
     * 设置块首
     *
     * @access public
     * @param string $block_name
     */

    public function setBlock($block_name)
    {
        if ( !$this->clearLayout ) {
            $this->current_block = $block_name;
            ob_end_clean();
            ob_start();
        }
    }

    /**
     * 设置块尾
     *
     * @access public
     * @param string $block_name
     */

    public function setBlockEnd($block_name)
    {
        if ( !$this->clearLayout ) {
            $content = ob_get_contents();
            ob_end_clean();
            $this->blocks[$block_name] = isset ($this->blocks[$block_name]) ?
                                         $this->blocks[$block_name] . $content :
                                         $content;
            ob_start();
        }
    }

    /**
     * 设置动态内容
     *
     * @access public
     * @param string $dynamic_name
     */

    public function setDynamic()
    {
	    $content = ob_get_contents();
		if ( !$this->current_block ) {
			$this->contents .= $content;
			$this->cacheContents .= $content;
		} else {
			$this->blocks[$this->current_block] .= $content;
		}
        ob_end_clean();
        ob_start();
    }

    /**
     * 设置动态内容结束
     *
     * @access public
     */

    public function setDynamicEnd()
    {
        $content = ob_get_contents();
        ob_end_clean();
        $content = str_replace('<@', '<?', $content);
        $content = str_replace('@>', '?>', $content);
		
		extract($this->vars);
        if ( !$this->dynamicCache ) {
			ob_start();
			eval("?>$content<?php ");
			$content = ob_get_contents();
			ob_end_clean();
			
			if( !$this->current_block ) {
				$this->contents .= $content;
			} else {
				$this->blocks[$this->current_block] .= $content;
			}
        } else {
			if ( !$this->current_block ) {
				$this->cacheContents .= $content;
			} else {
				$this->blocks[$this->current_block] .= $content;
			}
        }

        ob_start();
    }

    /**
     * 判断是否缓存
     *
     * @access public
     */

    public function isCached()
    {
        if ( $this->cached )
            return true;

        if ( !$this->cacheID )
            return false;

        if( !file_exists($this->cacheID) )
            return false;

        if( !($mtime = filemtime($this->cacheID)) )
            return false;

        if( ($mtime + $this->expire) < NOW ) {
            @unlink($this->cacheID);
            return false;
        } else {
            $this->cached = true;
            return true;
        }
    }

    /**
     * 显示视图内容
     *
     * @access public
     */

    public function display()
    {
        $filename = APPDIR . 'views' . DS . strtolower($this->file) . '.php';
        if ( !file_exists($filename) ) {
            throw new Exception('Unknown file' . $filename);
        }
        extract($this->vars);
        if ( $this->isCached() ) {
            include $this->cacheID;
        } else {
            ob_start();
            include $filename;
            foreach ( $this->blocks as $value ) {
                $this->contents .= $value;
            }

            if ( !$this->current_block )
                $this->contents .= ob_get_contents();
			
            ob_end_clean();
			echo $this->contents;
           
		    if( $this->isCache ) {
                
				$this->dynamicCache = true;
				$this->cacheContents = '';
				$this->blocks = array();
                ob_start();
                include $filename;
                foreach ( $this->blocks as $value ) {
                    $this->cacheContents .= $value;
                }

                if ( !$this->current_block )
               			$this->cacheContents .= ob_get_contents();

                ob_end_clean();

                if ( $fp = @fopen($this->cacheID, 'w') ) {
                    fwrite($fp, $this->cacheContents);
                    fclose($fp);
                } else {
                    throw new Exception("Unable to Write Cache");
                }
            }
        }
    }

    /**
     * 系统模板解析
     *
     * @access public
     * @param string $filename
     */

    public function sysView($filename = 'index')
    {
        $file = BASEDIR . 'systemfiles' . DS . 'views' . DS . $filename . '.php';
        if(!file_exists($file))
          throw new Exception("Unknown file '$file'");
          extract($this->vars);
          include($file);
    }
}
?>